package com.example.java_gobang2.game;

import com.example.java_gobang2.mapper.UserMapper;
import com.example.java_gobang2.model.MatchResponse;
import com.example.java_gobang2.model.Room;
import com.example.java_gobang2.model.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

@Slf4j
@Component
public class Matcher {
    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private RoomManager roomManager;

    @Autowired
    private UserMapper userMapper;

    private ObjectMapper objectMapper = new ObjectMapper();

    private Queue<User> fristQueue = new LinkedList<>();
    private Queue<User> nextQueue = new LinkedList<>();
    private Queue<User> lastQueue = new LinkedList<>();
    private Queue<User> aiQueue = new LinkedList<>();

    public Matcher() {
        Thread thread1 = new Thread(()->{
            init(fristQueue);
        });
        Thread thread2 = new Thread(()->{
            init(nextQueue);
        });
        Thread thread3 = new Thread(()->{
            init(lastQueue);
        });
        Thread thread4 = new Thread(()->{
            initAI(aiQueue);
        });
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }

    private void initAI(Queue<User> aiQueue) {
        synchronized (aiQueue) {
            try {
                while (aiQueue.isEmpty()) {
                    aiQueue.wait();
                }
                User user1 = aiQueue.poll();
                User user2 = userMapper.selectByUsername("ai");
                Room room = new Room();
                roomManager.setRooms(user1.getUserId(), room);
                roomManager.setRooms(user2.getUserId(), room);
                MatchResponse response = new MatchResponse();
                response.setMessage("AI匹配成功");
                log.info("AI匹配成功");

                onlineUserManager.getGameHall(user1.getUserId())
                        .sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                log.info("匹配消息发送成功");
            } catch (InterruptedException | IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void init(Queue<User> queue)  {
        synchronized (queue) {
            try {
                while (queue.size() < 2) {
                    log.info("while队列长度:{}",queue.size());
                    queue.wait();
                }
                User user1 = queue.poll();
                User user2 = queue.poll();
                Room room = new Room();
                roomManager.setRooms(user1.getUserId(), room);
                roomManager.setRooms(user2.getUserId(), room);
                MatchResponse response = new MatchResponse();
                response.setMessage("匹配成功");
                MatchResponse response2 = new MatchResponse();
                response2.setMessage("匹配成功");
                log.info("匹配成功");
                onlineUserManager.getGameHall(user1.getUserId())
                        .sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                onlineUserManager.getGameHall(user2.getUserId())
                        .sendMessage(new TextMessage(objectMapper.writeValueAsString(response2)));

            } catch (InterruptedException | IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void add(User user) {
        if (user.getScore() < 1500) {
            synchronized (fristQueue) {
                fristQueue.add(user);

                fristQueue.notify();
            }
        }else if (user.getScore() < 2000) {
            synchronized (nextQueue) {
                nextQueue.add(user);
                nextQueue.notify();
            }
        }else {
            synchronized (lastQueue) {
                lastQueue.add(user);
                lastQueue.notify();
            }
        }
    }

    public void addAI(User user) {
        synchronized (aiQueue) {
            aiQueue.add(user);
            aiQueue.notify();
        }
    }

    public void remove(User user) {
        if (user.getScore() < 1500) {
            synchronized (fristQueue) {
                fristQueue.remove(user);
            }
        }else if (user.getScore() < 2000) {
            synchronized (nextQueue) {
                nextQueue.remove(user);
            }
        }else {
            synchronized (lastQueue) {
                lastQueue.remove(user);
            }
        }
    }
}
